import {
  Injectable,
  NotFoundException,
  ConflictException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Category } from './category.entity';
import {
  CreateCategoryDto,
  UpdateCategoryDto,
  CategoryResponseDto,
} from './category.dto';
import { Song } from '../song/song.entity';

@Injectable()
export class CategoryService {
  constructor(
    @InjectRepository(Category)
    private categoryRepository: Repository<Category>,
    @InjectRepository(Song)
    private songRepository: Repository<Song>,
  ) {}

  // 将分类实体映射为响应DTO
  private mapToResponseDto(category: Category): CategoryResponseDto {
    const dto = new CategoryResponseDto();
    dto.id = category.id;
    dto.name = category.name;
    dto.description = category.description;
    dto.createdAt = category.createdAt;
    dto.updatedAt = category.updatedAt;
    return dto;
  }

  // 创建新分类
  async createCategory(
    createCategoryDto: CreateCategoryDto,
  ): Promise<CategoryResponseDto> {
    // 检查分类名称是否已存在
    const existingCategory = await this.categoryRepository.findOneBy({
      name: createCategoryDto.name,
    });
    if (existingCategory) {
      throw new ConflictException(
        `分类名称 "${createCategoryDto.name}" 已存在`,
      );
    }

    const category = this.categoryRepository.create(createCategoryDto);
    const savedCategory = await this.categoryRepository.save(category);
    return this.mapToResponseDto(savedCategory);
  }

  // 获取所有分类
  async getAllCategories(): Promise<CategoryResponseDto[]> {
    const categories = await this.categoryRepository.find();
    return categories.map((category) => this.mapToResponseDto(category));
  }

  // 获取单个分类
  async getCategoryById(id: number): Promise<CategoryResponseDto> {
    const category = await this.categoryRepository.findOneBy({ id });
    if (!category) {
      throw new NotFoundException(`分类ID ${id} 不存在`);
    }
    return this.mapToResponseDto(category);
  }

  // 更新分类
  async updateCategory(
    id: number,
    updateCategoryDto: UpdateCategoryDto,
  ): Promise<CategoryResponseDto> {
    const category = await this.categoryRepository.findOneBy({ id });
    if (!category) {
      throw new NotFoundException(`分类ID ${id} 不存在`);
    }

    // 检查新的分类名称是否已存在（如果提供了新名称）
    if (updateCategoryDto.name && updateCategoryDto.name !== category.name) {
      const existingCategory = await this.categoryRepository.findOneBy({
        name: updateCategoryDto.name,
      });
      if (existingCategory) {
        throw new ConflictException(
          `分类名称 "${updateCategoryDto.name}" 已存在`,
        );
      }
    }

    // 更新分类信息
    Object.assign(category, updateCategoryDto);
    const updatedCategory = await this.categoryRepository.save(category);
    return this.mapToResponseDto(updatedCategory);
  }

  // 删除分类
  async deleteCategory(id: number): Promise<void> {
    const result = await this.categoryRepository.delete(id);
    if (result.affected === 0) {
      throw new NotFoundException(`分类ID ${id} 不存在`);
    }
  }

  // 获取分类下的所有歌曲
  async getSongsByCategory(id: number): Promise<Song[]> {
    const category = await this.categoryRepository.findOne({
      where: { id },
      relations: ['songs'],
    });
    if (!category) {
      throw new NotFoundException(`分类ID ${id} 不存在`);
    }
    return category.songs;
  }

  // 将歌曲添加到分类
  async addSongToCategory(categoryId: number, songId: number): Promise<void> {
    const category = await this.categoryRepository.findOne({
      where: { id: categoryId },
      relations: ['songs'],
    });
    if (!category) {
      throw new NotFoundException(`分类ID ${categoryId} 不存在`);
    }

    const song = await this.songRepository.findOneBy({ id: songId });
    if (!song) {
      throw new NotFoundException(`歌曲ID ${songId} 不存在`);
    }

    // 检查歌曲是否已在分类中
    const isSongInCategory = category.songs.some((s) => s.id === songId);
    if (!isSongInCategory) {
      category.songs.push(song);
      await this.categoryRepository.save(category);
    }
  }

  // 从分类中移除歌曲
  async removeSongFromCategory(
    categoryId: number,
    songId: number,
  ): Promise<void> {
    const category = await this.categoryRepository.findOne({
      where: { id: categoryId },
      relations: ['songs'],
    });
    if (!category) {
      throw new NotFoundException(`分类ID ${categoryId} 不存在`);
    }

    // 过滤掉要移除的歌曲
    category.songs = category.songs.filter((song) => song.id !== songId);
    await this.categoryRepository.save(category);
  }
}
